// -----------------------------------------------------------------------
// <copyright file="ResponseHeaderCreator.cs" company="Softserve">
// Made by VK
// </copyright>
// -----------------------------------------------------------------------
namespace WebServer.BusinessLogic
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Globalization;
    using System.Linq;
    using WebServer.BusinessLogic.Web;

    /// <summary>
    /// Class for Collection of Headers
    /// </summary>
    public class HeadersCollection : Collection<string>
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="HeadersCollection" /> class.
        /// </summary>
        public HeadersCollection() : base(new List<string>())
        {
        }

        /// <summary>
        /// Exists match in List
        /// </summary>
        /// <param name="match">match string</param>
        /// <returns>exists or not</returns>
        public bool Exists(Predicate<string> match)
        {
            var items = (List<string>)this.Items;
            return items.Exists(match);
        }
    }

    /// <summary>
    /// Class for creating Response Header
    /// </summary>
    public class ResponseHeaderCreator
    {
        /*
         * Response should look like this
         * 
        HTTP/1.1 200 OK
        Date: Sun, 09 Mar 2008 16:05:07 GMT
        Connection: close
        Server: MyServer/1.0
        Accept-Ranges: bytes
        Content-Type: text/html
        Content-Length: 170
        Last-Modified: Sun, 09 Mar 2008 16:05:07 GMT
         */

        /// <summary>
        /// Field for collection of headers
        /// </summary>
        private HeadersCollection headersList;

        /// <summary>
        /// Response object
        /// </summary>
        private Response response;

        /// <summary>
        /// Initializes a new instance of the <see cref="ResponseHeaderCreator" /> class.
        /// </summary>
        /// <param name="response">response object</param>
        public ResponseHeaderCreator(Response response)
        {
            this.headersList = new HeadersCollection();
            this.response = response;
        }

        /// <summary>
        /// Creates list of parameters for the Header
        /// </summary>
        /// <returns>object of HeaderCollection class</returns>
        public HeadersCollection Create()
        {
            // add Header with status and description
            this.headersList.Add(string.Format("{0} {1} {2}", this.response.HttpVersion, this.response.HttpResponseCode, this.response.HttpResponseCodeDescription)); // HTTP/1.0 200 OK
            
            // add current Date
            this.headersList.Add(string.Format(CultureInfo.InvariantCulture, "Date: {0}", DateTime.Now.ToString("r", CultureInfo.InvariantCulture)));

            // add Connection if needed
            if (this.response.KeepAlive)
            {
                this.response.ConnectionStatus = "Keep-Alive";
            }
            if (!string.IsNullOrEmpty(this.response.ConnectionStatus))
            {
                this.headersList.Add(string.Format("Connection: {0}", this.response.ConnectionStatus));
            }

            // add Location if needed
            if (!string.IsNullOrEmpty(this.response.Location))
            {
                this.headersList.Add(string.Format("Location: {0}", this.response.Location));
            }

            // add Server name and version
            this.headersList.Add(string.Format("Server: {0}/{1}", Configurator.Instance.ServerName, Configurator.Instance.Version));

            // add Accept ranges if needed
            if (this.response.AcceptsRanges)
            {
                this.headersList.Add(string.Format("Accept-Ranges: {0}", this.response.AcceptsRanges ? "bytes" : "none"));
            }

            // add Mime Type
            if (!string.IsNullOrEmpty(this.response.MimeType))
            {
                this.headersList.Add(string.Format("Content-Type: {0}", this.response.MimeType));
            }

            // add length of Data
            if (this.response.Data != null)
            {
                this.headersList.Add(string.Format("Content-Length: {0}", this.response.Data.Length));
            }

            if (this.response.ContentEncoding != null)
            {
                this.headersList.Add(string.Format("Content-Encoding: {0}", this.response.ContentEncoding));
            }

            // add last modified date of file, if Handler did set this value
            if (this.response.LastModified > DateTime.MinValue)
            {
                this.headersList.Add(string.Format(CultureInfo.InvariantCulture, "Last-Modified: {0}", string.Format("{0:r}", this.response.LastModified)));
            }

            // add set-cookies
            if (this.response.Cookies.Length > 0)
            {
                foreach (Cookie cookie in this.response.Cookies.Items)
                {
                    string pathStr = string.Empty;
                    if (cookie.Path != null)
                    {
                        pathStr = string.Format("; Path={0}", cookie.Path);
                    }

                    string expiresStr = string.Empty;
                    if (cookie.Expires.HasValue)
                    {
                        expiresStr = string.Format(CultureInfo.InvariantCulture, "; Expires={0:r}", cookie.Expires.Value);
                    }

                    this.headersList.Add(string.Format("Set-Cookie: {0}={1}{2}{3}", cookie.Key, cookie.Value, pathStr, expiresStr));
                }                
            }

            return this.headersList;
        }

        /// <summary>
        /// Override ToString method to return proper format for HEADER
        /// </summary>
        /// <returns>header in proper format</returns>
        public override string ToString()
        {
            const string Separator = "\r\n";
            return string.Join(Separator, this.headersList.ToArray()) + Separator;
        }
    }
}